﻿using Common.Communi.Model;
using ControllerManageServer.Controller;
using ControllerManageServer.Controller.Aioi;
using ControllerManageServer.Controller.Prada;
using ControllerManageServer.Handler;
using Controller.Enum;
using Controller.Model;
using Controller.Utils;
using Leeder.Logger;
using Leeder.Util;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Configuration;
using System.IO.Ports;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace ControllerManageServer
{
    class MainBLL
    {
        #region 变量声明

        /// <summary>
        /// 是否停止
        /// </summary>
        private bool isStop;
        /// <summary>
        /// socket数据服务
        /// </summary>
        private DpsSocketServerHandler socketServer;
        /// <summary>
        /// 日志对象
        /// </summary>
        private LogOperate LogObj;
        /// <summary>
        /// Socket服务接收数据的客户端和对应的接收数据的队列, key:客户端的ip:port，
        /// </summary>
        private ConcurrentDictionary<string, ConcurrentQueue<byte[]>> serverReceiveDictionary;
        /// <summary>
        /// 发送数据队列字典,key:ip:port,value:发送数据的队列
        /// </summary>
        private ConcurrentDictionary<string, ConcurrentQueue<byte[]>> serverSendDictionary;
        /// <summary>
        /// 控制器集,key:ip:port, value:控制器
        /// </summary>
        private ConcurrentDictionary<string, IController> controllerCollection;
        /// <summary>
        /// Socket服务的数据处理线程
        /// </summary>
        private Thread socketServerDataControlThread;

        #endregion 变量声明

        /// <summary>
        /// 启用
        /// </summary>
        public void Start()
        {
            LogObj = Log.GetLogger(GetType());

            try
            {
                Init();
                // 初始化控制器
                InitController();
                // Socket Server
                socketServer = new DpsSocketServerHandler(ConfigInfo.ListenIP, ConfigInfo.ListenPort);
                socketServer.OnDataReceive += SocketServerDataReceive;
                socketServer.GetSendDataEvent += GetSendData;
                socketServer.Start();
                // socket服务数据处理线程
                socketServerDataControlThread = new Thread(SocketServerDataControlFunction) { IsBackground = true, Name = "Socket Server Data Control Thread" };
                socketServerDataControlThread.Start();

                LogObj.Info("Controller Manage Server Start Success!");
            }
            catch (Exception ex)
            {
                LogObj.Error($"{ex.Message}");
            }
        }

        #region 初始化

        /// <summary>
        /// 初始化
        /// </summary>
        private void Init()
        {
            isStop = false;
            serverSendDictionary = new ConcurrentDictionary<string, ConcurrentQueue<byte[]>>();
            serverReceiveDictionary = new ConcurrentDictionary<string, ConcurrentQueue<byte[]>>();
            controllerCollection = new ConcurrentDictionary<string, IController>();
        }

        /// <summary>
        /// 初始化控制器
        /// </summary>
        private void InitController()
        {
            //int resendCount = -1;
            int controllerNumber = ConfigHelper.GetSettingVal(ConfigurationManager.AppSettings, "ControllerNumber", p => int.Parse(p), 0);
            
            for (int i = 1; i <= controllerNumber; i++)
            {
                string controllerInfo = ConfigHelper.GetSettingVal(ConfigurationManager.AppSettings, $"Controller{i}", p => p, null);
                try
                {
                    if (string.IsNullOrEmpty(controllerInfo)) continue;
                    
                    ConfigController(controllerInfo, i);
                }
                catch (Exception ex)
                {
                    LogObj.Error(ExceptionType.BusinessException, ex, $"解析控制器信息失败!Controller{i} --> {controllerInfo}");
                }
            }
        }

        /// <summary>
        /// 获取控制器
        /// </summary>
        /// <param name="iType">控制器类型</param>
        /// <param name="iIpAddress">IP地址</param>
        /// <param name="iPort">端口号</param>
        /// <returns></returns>
        private void ConfigController(string iControllerInfo, int iControllerNumber)
        {
            // 控制器类型,ip,端口
            string[] arr = iControllerInfo.Replace('，', ',').Split(',');
            int type = int.Parse(arr[0]);
            if (type == 1)
            {
                if (arr.Length < 3)
                {
                    LogObj.Error(ExceptionType.BusinessException, null, $"错误的控制器信息!Controller{iControllerNumber} --> {iControllerInfo}");
                    return;
                }
                AioiController controller = new AioiController(arr[1], int.Parse(arr[2]));
                controller.OnDataReceive += Controller_OnDataReceive;
                controller.Start();

                int resendCount = -1;
                if (arr.Length > 3)
                {
                    int.TryParse(arr[3], out resendCount);
                }
                controller.ReSendCount = resendCount;
                controllerCollection.TryAdd(controller.ToString(), controller);
                //controller.SetSendData(new BaseLabelDevice().Init());
                return;
            }
            else if (type == 2)
            {
                if (arr.Length < 3)
                {
                    LogObj.Error(ExceptionType.BusinessException, null, $"错误的控制器信息!Colltroller{iControllerNumber} --> {iControllerInfo}");
                }
                int checkIntervalTime = 0;

                SerialPortInfoModel serialPortInfoModel = GetSerialPortInfo(arr);
                if (arr.Length > 6)
                {
                    int.TryParse(arr[6], out checkIntervalTime);
                }
                if (checkIntervalTime <= 0) checkIntervalTime = 3000;

                PradaRfidWatchController pradaRfidWatch = new PradaRfidWatchController(serialPortInfoModel, checkIntervalTime);
                pradaRfidWatch.OnDataReceive += Controller_OnDataReceive;
                pradaRfidWatch.Start();

                controllerCollection.TryAdd(pradaRfidWatch.ToString(), pradaRfidWatch);
            }
            else
            {
                LogObj.Error(ExceptionType.BusinessException, null, $"错误的控制器类型!Controller{iControllerNumber} --> {iControllerInfo}");
            }
        }

        /// <summary>
        /// 获取串口信息
        /// </summary>
        /// <param name="arr"></param>
        /// <returns></returns>
        private SerialPortInfoModel GetSerialPortInfo(string[] arr) {
            int dataBit = 8;
            Parity parity= Parity.None;
            int baudRate = 9600;
            StopBits stopBit = StopBits.One;

            if(arr.Length > 2)
            {
                baudRate = int.Parse(arr[2]);
            }
            if(arr.Length > 5) { 
                stopBit = (StopBits)int.Parse(arr[5]);
            }
            if (arr.Length > 3)
            {
                arr[3] = arr[3].ToLower();
                if (arr[3].Equals("o"))
                {
                    parity = Parity.Odd;
                }
                else if (arr[3].Equals("e"))
                {
                    parity = Parity.Even;
                }
                else if (arr[3].Equals("m"))
                {
                    parity = Parity.Mark;
                }
                else if (arr[3].Equals("s"))
                {
                    parity = Parity.Space;
                }
                else
                {
                    parity = Parity.None;
                }
            }
            if(arr.Length > 4) { dataBit = int.Parse(arr[4]); }
            return new SerialPortInfoModel(arr[1], baudRate, dataBit, parity, stopBit);
        }

        #endregion  初始化

        /// <summary>
        /// 停止
        /// </summary>
        public void Stop()
        {
            isStop = true;
            socketServer.Stop();
            if (null != socketServerDataControlThread)
            {
                try { socketServerDataControlThread.Abort(); } catch { }
            }
        }

        #region 控制器处理

        /// <summary>
        /// 处理控制器接收到的数据
        /// </summary>
        /// <param name="key">ip:port</param>
        /// <param name="obj"></param>
        private void Controller_OnDataReceive(string key, ServerPacketModel obj)
        {
            SetServerSocketSendData(key, obj);
        }

        #endregion 控制器处理

        #region Socket服务处理

        /// <summary>
        /// socket服务的数据接收
        /// </summary>
        /// <param name="key">ip:port</param>
        /// <param name="iData">接收的数据</param>
        public void SocketServerDataReceive(string key, byte[] iData)
        {
            if (iData[0] != ServerPacketModel.HEAT || iData[iData.Length - 1] != ServerPacketModel.TAIL)
            {
                LogObj.Error($"接收数据错误!接收的帧头和帧尾不匹配!{ByteUtils.ByteArrayToHexString(iData)}");
                return;
            }
            if (!serverReceiveDictionary.ContainsKey(key)) serverReceiveDictionary.TryAdd(key, new ConcurrentQueue<byte[]>());
            serverReceiveDictionary[key].Enqueue(iData);
        }

        /// <summary>
        /// 获取发送数据
        /// </summary>
        /// <param name="key">ip:port</param>
        /// <returns></returns>
        public byte[] GetSendData(string key)
        {
            if (!serverSendDictionary.ContainsKey(key)) return null;
            byte[] result;
            if (serverSendDictionary[key].TryDequeue(out result))
            {
                return result;
            }
            return null;
        }

        /// <summary>
        /// Socket服务的数据处理线程
        /// </summary>
        private void SocketServerDataControlFunction()
        {
            byte[] temp = null;
            ServerPacketModel serverPacketModel = new ServerPacketModel();
            while (!isStop)
            {
                try
                {
                    // 遍历每个客户端的消息
                    foreach (string key in serverReceiveDictionary.Keys)
                    {
                        if (serverReceiveDictionary[key].IsEmpty ||
                            !serverReceiveDictionary[key].TryDequeue(out temp)) continue;
                        // 解析基础信息
                        serverPacketModel.UnSerialize(temp);
                        if (serverPacketModel.CmdType == 0)
                        {
                            LogObj.Error($"无法解析的命令类型[{serverPacketModel.CmdType}]");
                            continue;
                        }
                        // 心跳不需要做处理,当Socket服务接收到一个完整包信息时会查看队列是否有要发送的数据,
                        // 如果没有则发现心跳包,如果有则发送数据
                        if (serverPacketModel.CmdType == CommunicationCmdTypeEnum.HEART_BEAT) continue;
                        ServerPacketModel model = null;
                        switch (serverPacketModel.CmdType)
                        {
                            case CommunicationCmdTypeEnum.ACTION:
                                model = new ActionPacketModel();
                                break;
                            case CommunicationCmdTypeEnum.CANCEL:
                                model = new CancelPacketModel();
                                break;
                            case CommunicationCmdTypeEnum.GET_LABEL_STATE:
                                model = new GetLabelStatePacketModel();
                                break;
                            case CommunicationCmdTypeEnum.REGISTRATION_DEVICE:
                                model = new RegistrationDevicePacketModel();
                                break;
                            case CommunicationCmdTypeEnum.GET_LABEL_VOLTAGE:
                                model = new GetDeviceVoltagePacketModel();
                                break;
                            case CommunicationCmdTypeEnum.DISPLAY_DATA:
                                model = new DisplayDataPacketModel();
                                break;
                            case CommunicationCmdTypeEnum.VIBRATION:
                                model = new VibrationPacketModel();
                                break;
                            case CommunicationCmdTypeEnum.WRITE_RFID:
                                model = new WriteRfidPacketModel();
                                break;
                            case CommunicationCmdTypeEnum.SETTING_PANID_CHANNEL:
                                model = new SettingPanIdChannelPacketModel();
                                break;
                        }
                        if (null != model)
                        {
                            model.UnSerialize(temp);
                            if(model.CmdType == CommunicationCmdTypeEnum.ACTION)
                                LogObj.Info($"控制地址:{((ActionPacketModel)model).AddressList[0]}\t显示字符:{((ActionPacketModel)model).ControlModel.Seq}");
                            if (controllerCollection.ContainsKey(model.ControllerKey))
                            {
                                controllerCollection[model.ControllerKey].SetSendData(key, model);
                            }
                            else
                            {
                                SetServerSocketSendData(key, new ControllerStatePacketModel { /*IpAddress = model.IpAddress, Port = model.Port,*/ControllerKey = model.ControllerKey,  State = ControllerStateEnum.UNCONFIGURED});
                            }
                        }
                    }
                    Thread.Sleep(5);
                }
                catch (Exception ex)
                {
                    LogObj.Error(ExceptionType.BusinessException, ex, $"Socket Server Data Control Error!");
                }
            }
        }

        /// <summary>
        /// 设置Socket服务发送数据
        /// </summary>
        /// <param name="key"></param>
        /// <param name="iModel"></param>
        private void SetServerSocketSendData(string key, ServerPacketModel iModel)
        {
            if (!serverSendDictionary.ContainsKey(key)) serverSendDictionary.TryAdd(key, new ConcurrentQueue<byte[]>());
            serverSendDictionary[key].Enqueue(iModel.Serialize());
        }

        #endregion Socket服务处理
    }
}
